package com.trimps.wifi.service.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.trimps.wifi.pojo.Device;
import com.trimps.wifi.service.IDevManagerService;
import com.trimps.wifi.service.IDevService;

@Service("devManagerService")
public class DevManagerServiceImpl implements IDevManagerService {
    private static final Logger logger = Logger.getLogger(DevManagerServiceImpl.class);
    
    @Autowired
    private IDevService devService;

	@Override
	public void handle(String msg, String remoteIp, OutputStream os) throws IOException {
		String decStr = URLDecoder.decode(msg, "utf-8");
		
		logger.debug("[received]: "+decStr);
		String[] strs = decStr.split("\n");
		StringBuffer sb = new StringBuffer();
		for(String str : strs ) {
			Map<String, String> fields = parseParams(str);
			Map<String, String> rstMap = null;
			String op = fields.get("op");
			switch (op) {
			case "0":
				rstMap = handHB(fields);
				break;
			case "2":
				rstMap = handReg(remoteIp, fields);
				break;
			case "20":
				rstMap = handCfg(fields);
				break;
			default:
				logger.info("unknown option:"+op+" :: "+fields);
				break;
			}
			if(rstMap != null) {
				sb.append(StringUtils.join(rstMap.entrySet(), "&")).append("\n");
			}
		}
		logger.debug("[response]: " + sb.toString());
		byte[] buffer  = encodeRsp(sb.toString());
		logger.debug("[buffer]: " + new String(buffer));
		os.write(buffer);
		os.flush();
	}

	/**
	 * 处理管理心跳协议-0
	 * @param fields
	 * @throws IOException 
	 */
	private Map<String, String> handHB(Map<String, String> fields) throws IOException{
		Map<String, String> map = new LinkedHashMap<String, String>();
		map.put("op", "100");
		map.put("interval", "60");
		updateCfg(fields);
		return map;
		
		/*String devMac = fields.get("dev_mac");
		if(devCfgSync.get(devMac) == null) {
			//respHB(null);
		}else{
			DeviceCfg cfg = devCfgMapper.getDevCfgByDevNo(devMac);
			respConfig(fields);
		}*/
	}
	
	/**
	 * 处理设备注册协议-2
	 * 探针启动或更改注册信息后上报至中心
	 * @param fields
	 * @throws IOException 
	 */
	private Map<String, String>  handReg(String remoteIp, Map<String, String> fields) throws IOException {
		Map<String, String> map = new LinkedHashMap<String, String>();
		map.put("op", "102"); // 操作码
		map.put("ret", "0"); // ret 注册结果 0-成功； 1-失败 
		
		fields.put("remoteIp", remoteIp);
		updateCfg(fields);
		
		return map;
	}
	
	/**
	 * 处理设备配置协议-20
	 * 1）当设备启动时，上报配置参数给中心；
	 * 2）当设备更改配置参数时，通知中心同步；
	 * 3）当中心更改配置参数时，通知设备同步。
	 * @param fields
	 */
	private Map<String, String> handCfg(Map<String, String> fields) {
		Map<String, String> map = new LinkedHashMap<String, String>();
		map.put("op", "120"); // 操作码
		map.put("ret", "0"); // ret 注册结果 0-成功； 1-失败 
		
		updateCfg(fields);
		return map;
	}
	
	private void updateCfg (Map<String, String> fields) {
		String devNo = fields.get("dev_id");
		Device dev = devService.getByDevNo(devNo);
		if(dev != null) {
			if(fields.get("dev_name") != null) {
				dev.setDevName(fields.get("dev_name"));
			}
			if(fields.get("dev_sw") != null) {
				dev.setDevVersion(fields.get("dev_sw"));
			}
			if(fields.get("dev_addr") != null) {
				dev.setAddr(fields.get("dev_addr"));
			}
			if(fields.get("dev_lat") != null) {
				dev.setLatitude(fields.get("dev_lat"));
			}
			if(fields.get("dev_lng") != null) {
				dev.setLongitude(fields.get("dev_lng"));
			}
			if(fields.get("dev_mac") != null) {
				dev.setMacList(fields.get("dev_mac"));
			}
			dev.setLastActiveTime(new Date());
			if(fields.get("remoteIp") != null) {
				dev.setRemoteIp(fields.get("remoteIp"));
			}
			devService.saveDevice(dev);
		}
	}
    
    private Map<String, String> parseParams(String params) {
    	Map<String, String> fields = new HashMap<String, String>();
    	String[] strs = params.split("&");
    	for(String str : strs ) {
    		String[] field = str.split("=");
    		if(field.length == 2) {
    			fields.put(field[0], field[1]);
    		}else {
    			fields.put(field[0], "");
    		}
		}
		return fields;
	}

	private byte[] encodeRsp(String str) {
		byte[] buffer = str.getBytes();
		for (int i = 0; i < buffer.length; i++) {
			buffer[i] ^= 0xAA;
		}
		return buffer;
	}

}
